package com.hunan.api.catv.service.biz.prize;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hunan.api.catv.entity.dto.IqyiPopRuleDto;
import com.hunan.api.catv.entity.dto.IqyiPrizeDTO;
import com.hunan.api.catv.entity.po.MemberAccountRelated;
import com.hunan.api.catv.entity.po.PrizeReceiveRecord;
import com.hunan.api.catv.entity.po.PrizeStore;
import com.hunan.api.catv.mq.MqConstants;
import com.hunan.api.catv.service.ResultService;
import com.hunan.api.catv.service.biz.mq.MqBiz;
import com.hunan.api.catv.service.biz.system.SystemDictBiz;
import com.hunan.api.catv.utils.GsonUtils;
import com.hunan.api.catv.utils.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author jiang zhuan
 * @version 1.0
 * @description 描述
 * @date 2021/5/8 0008
 * @package com.hunan.api.catv.service.biz.prize
 * @company 湖南有线
 */
@Service
public class PrizeBiz extends ResultService {


    private static final String IQYI_POP_SWITCH = "iqyi_pop_switch";
    @Autowired
    MqBiz mqBiz;

    @Autowired
    SystemDictBiz systemDictBiz;

    @Autowired
    RedisUtils redisUtils;

    public Map<String, Object> getPrizeInfo(Integer memberId, String accountId, String version) {
        Map<String, Object> result = new HashMap<>();
        result.put("popFlag", false);
        IqyiPopRuleDto iqyiPopRuleDto = JSONUtil.toBean(systemDictBiz.getStringByKey(IQYI_POP_SWITCH), IqyiPopRuleDto.class);
        if (iqyiPopRuleDto.getPopFlag() && StringUtils.isNotBlank(version) && Integer.parseInt(version) > 199) {
            List<MemberAccountRelated> memberAccountRelateds = new MemberAccountRelated().selectList(new QueryWrapper<MemberAccountRelated>().eq(MemberAccountRelated.TYPE, 2).and(o -> o.eq(MemberAccountRelated.MEMBER_ID, memberId).or().eq(MemberAccountRelated.ACCOUNT_ID, accountId)));
            if (memberAccountRelateds.isEmpty()) {
                List<PrizeStore> prizeStores = new PrizeStore().selectList(new QueryWrapper<PrizeStore>().eq(PrizeStore.DELETED, 1).eq(PrizeStore.STATE, 1).eq(PrizeStore.ACTIVITY_TYPE, 1).eq(PrizeStore.TYPE, 0).orderByAsc(PrizeStore.ID));
                if (prizeStores.isEmpty()) {
                } else {
                    PrizeStore prizeStore = prizeStores.get(0);
                    Boolean nx = redisUtils.setNX("prizeId_lock_" + prizeStore.getId(), "1", 30, TimeUnit.SECONDS);
                    if (!nx) {
                        for (int i = 0; i < 100; i++) {
                            prizeStores = new PrizeStore().selectList(new QueryWrapper<PrizeStore>().eq(PrizeStore.DELETED, 1).eq(PrizeStore.STATE, 1).eq(PrizeStore.ACTIVITY_TYPE, 1).eq(PrizeStore.TYPE, 0).orderByAsc(PrizeStore.ID));
                            if (prizeStores.isEmpty()) {
                                break;
                            }
                            prizeStore = prizeStores.get(0);
                            nx = redisUtils.setNX("prizeId_lock_" + prizeStore.getId(), "1", 30, TimeUnit.SECONDS);
                            if (nx) {
                                result.put("popFlag", true);
                                prizeStore.setState(3);
                                prizeStore.setLockingMemberId(memberId);
                                prizeStore.setLockingTime(new Date());
                                prizeStore.updateById();
                                redisUtils.hset("lockedPrizesMap", String.valueOf(memberId), prizeStore, TimeUnit.DAYS.toSeconds(1));
                                break;
                            }
                        }
                    } else {
                        result.put("popFlag", true);
                        prizeStore.setState(3);
                        prizeStore.setLockingMemberId(memberId);
                        prizeStore.setLockingTime(new Date());
                        prizeStore.updateById();
                        redisUtils.hset("lockedPrizesMap", String.valueOf(memberId), prizeStore, TimeUnit.DAYS.toSeconds(1));
                    }
                }
            }
        }
        return result;
    }

    @Transactional
    public Object accept(Integer memberId, Integer type, String deviceId, String remoteIp) {

//        PrizeStore prizeStore = new PrizeStore().selectOne(new QueryWrapper<PrizeStore>().eq(PrizeStore.STATE, 3).eq(PrizeStore.LOCKING_MEMBER_ID, memberId).eq(PrizeStore.ACTIVITY_TYPE, 1).eq(PrizeStore.DELETED, 1).eq(PrizeStore.TYPE, 0));
        PrizeStore prizeStore = (PrizeStore) redisUtils.hget("lockedPrizesMap", String.valueOf(memberId));
        recordAndSendSMS(memberId, type, deviceId, remoteIp, prizeStore.getId());
        redisUtils.hdel("lockedPrizesMap", String.valueOf(memberId));
        if (type == 1) {
            if (prizeStore == null) {
                return buildFail("未查询到锁定奖品或未在时限内领取，奖品已失效");
            }
            prizeStore.setState(2);
            prizeStore.updateById();
        } else {
            if (prizeStore == null) {
                return buildFail("");
            }
            prizeStore.setState(1);
            prizeStore.setLockingTime(null);
            prizeStore.setLockingMemberId(null);
            prizeStore.updateById();
            return buildOK("");
        }
        IqyiPrizeDTO iqyiPrizeDTO = new IqyiPrizeDTO();
        BeanUtil.copyProperties(prizeStore, iqyiPrizeDTO);
        JSONObject extend = JSONUtil.parseObj(prizeStore.getExtend());
        iqyiPrizeDTO.setActivationCode(extend.get("activationCode").toString());
        iqyiPrizeDTO.setCheckCode(extend.get("checkCode").toString());
        iqyiPrizeDTO.setSerialNumber(extend.get("serialNumber").toString());
        iqyiPrizeDTO.setDescription(iqyiPrizeDTO.getDescription() == null ? "" : iqyiPrizeDTO.getDescription());

        return buildOK(iqyiPrizeDTO);
    }

    private void recordAndSendSMS(Integer memberId, Integer type, String deviceId, String remoteIp, Integer prizeId) {
        PrizeReceiveRecord prizeReceiveRecord = new PrizeReceiveRecord();
        prizeReceiveRecord.setMemberId(memberId);
        prizeReceiveRecord.setMemberIp(remoteIp);
        prizeReceiveRecord.setMemberMac(deviceId);
        prizeReceiveRecord.setState(type == 1 ? 1 : 0);
        prizeReceiveRecord.setReceiveTime(new Date());
        prizeReceiveRecord.setActivityType(1);
        prizeReceiveRecord.setDeleted(1);
        prizeReceiveRecord.setPrizeId(prizeId);
        mqBiz.push(MqConstants.RECEIVE_IQIYI_SEND_SMS_EXCHANGE, MqConstants.RECEIVE_IQIYI_SEND_SMS_ROUTINGKEY, GsonUtils.toJson(prizeReceiveRecord));
    }


    /**
     * 恢复未领取锁定的爱奇艺权益，8小时执行一次
     */
    @Scheduled(fixedDelay = 28800000L)
    public void changeUnReciveLockingPrizeJob() {
        try {
            if (!redisUtils.setNX("ChangeUnReciveLockingPrizeFlag", "1", 30, TimeUnit.SECONDS)) {
                log.info("任务已有节点执行");
                return;
            }
            List<PrizeStore> prizeStores = new PrizeStore().selectList(new QueryWrapper<PrizeStore>().eq(PrizeStore.DELETED, 1).eq(PrizeStore.ACTIVITY_TYPE, 1).eq(PrizeStore.STATE, 3).eq(PrizeStore.TYPE, 0));
            prizeStores.parallelStream().forEach(prizeStore -> {
                Date lockingTime = prizeStore.getLockingTime();
                LocalDateTime lockingDateTime = lockingTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                if (lockingDateTime.plusDays(1L).compareTo(LocalDateTime.now()) < 0) {
                    prizeStore.setLockingMemberId(null);
                    prizeStore.setLockingTime(null);
                    prizeStore.setState(1);
                    prizeStore.updateById();
                }
            });
        } catch (Exception e) {
            log.error("未领取奖品超时恢复任务异常：{}", e);
        } finally {
            //任务完成后，释放redis锁
            redisUtils.del("ChangeUnReciveLockingPrizeFlag");
        }
    }

}
